package com.kalvan.core.http;

import com.alibaba.fastjson.JSON;
import com.kalvan.core.exception.BizException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.*;
import org.apache.http.client.CookieStore;
import org.apache.http.client.config.CookieSpecs;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.protocol.HttpClientContext;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.BasicCookieStore;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

/**
 * @author chenliang
 */
@Slf4j
public class RequestClient {
    /**
     * 全局请求设置
     */
    static RequestConfig globalConfig = RequestConfig.custom().setCookieSpec(CookieSpecs.STANDARD).build();
    /**
     * 创建cookie store的本地实例
     */

    static CookieStore cookieStore = new BasicCookieStore();
    /**
     * 创建HttpClient上下文
     */
    static HttpClientContext context = HttpClientContext.create();

    /**
     * 创建一个HttpClient
     **/
    static CloseableHttpClient client = HttpClients.custom().setDefaultRequestConfig(globalConfig)
            .setDefaultCookieStore(cookieStore).build();


    /**
     * 超时时间
     */
    static RequestConfig defaultRequestConfig = RequestConfig.custom()
            .setConnectTimeout(3000).setConnectionRequestTimeout(1000)
            .setSocketTimeout(5000).build();

    /**
     * 发送通知返回json握手报文
     * 默认连接超时时间3秒、读超时时间5秒
     * 返回 {code:0000,msg:xxx} code=0000表示成功
     *
     * @param url
     * @param json
     * @return
     * @throws Exception
     */
    public static void sendNotify(String url, String json) throws Exception {
        HttpPost httpPost = new HttpPost(url);
        httpPost.setConfig(defaultRequestConfig);
        StringEntity stringEntity = new StringEntity(json, "UTF-8");
        stringEntity.setContentEncoding("UTF-8");
        stringEntity.setContentType("application/json");
        httpPost.setEntity(stringEntity);
        log.info("request url:{}", url);
        CloseableHttpResponse res = client.execute(httpPost, context);
        try {
            String response = printResponse(res);
            response = response.replaceAll("\r|\n", "");
            if (!"0000".equals(response) && res.getStatusLine().getStatusCode() != 200) {
                log.error(StringUtils.left(response, 30));
                throw new BizException("返回握手报文不合法");
            }
        } finally {
            res.close();
//          log.info(response);
        }
    }


    /**
     * 请求post发送json
     *
     * @param url
     * @param json
     * @return
     * @throws Exception
     */
    public static String doPostJson(String url, String json, RequestConfig requestConfig) throws Exception {
        HttpPost httpPost = new HttpPost(url);
        httpPost.setConfig(requestConfig);
        StringEntity stringEntity = new StringEntity(json, "UTF-8");
        stringEntity.setContentEncoding("UTF-8");
        stringEntity.setContentType("application/json");
        httpPost.setEntity(stringEntity);
        log.info("request url:{}", url);
        log.debug("request params:{}", json);
        CloseableHttpResponse res = client.execute(httpPost, context);
        String response = printResponse(res);
        res.close();
        log.info("request end");
        log.debug("response : {}", response);
        return response;
    }

    /**
     * 请求get
     *
     * @param url
     * @param parameterMap
     * @return
     * @throws Exception
     */
    public static String doGet(String url, Map<String, String> parameterMap, RequestConfig requestConfig) throws Exception {
        List<NameValuePair> pairs = new ArrayList<>();
        for (Map.Entry<String, String> entry : parameterMap.entrySet()) {
            pairs.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
        }
        URIBuilder builder = new URIBuilder(url);
        builder.setParameters(pairs);
        HttpGet httpGet = new HttpGet(builder.build());
        httpGet.setConfig(requestConfig);
        log.info("request url:{}", url);
        log.debug("request params:{}", JSON.toJSONString(parameterMap));
        CloseableHttpResponse res = client.execute(httpGet, context);
        String response = printResponse(res);
        res.close();
        log.info("request end");
        log.debug("response : {}", response);
        return response;
    }

    /**
     * 请求get
     *
     * @param url
     * @return
     * @throws Exception
     */
    public static String doGet(String url, RequestConfig requestConfig) throws Exception {
        HttpGet httpGet = new HttpGet(url);
        httpGet.setConfig(requestConfig);
        log.info("request url:{}", url);
        CloseableHttpResponse res = client.execute(httpGet, context);
        String response = printResponse(res);
        res.close();
        log.info("request end");
        log.debug("response : {}", response);
        return response;
    }

    /**
     * 请求post
     *
     * @param url
     * @param parameterMap
     * @return
     * @throws Exception
     */
    public static String doPost(String url, Map parameterMap, RequestConfig requestConfig) throws Exception {
        HttpPost httpPost = new HttpPost(url);
        httpPost.setConfig(requestConfig);
        UrlEncodedFormEntity urlEncodedFormEntity = new UrlEncodedFormEntity(
                getParam(parameterMap), "UTF-8");
        httpPost.setEntity(urlEncodedFormEntity);
        log.info("request url:{}", url);
        log.info("request params:{}", JSON.toJSONString(parameterMap));
        CloseableHttpResponse res = client.execute(httpPost, context);
        String response = printResponse(res);
        res.close();
        log.info("request end");
        log.debug("response : {}", response);
        return response;
    }

    public static List<NameValuePair> getParam(Map parameterMap) {
        List<NameValuePair> param = new ArrayList<NameValuePair>();
        Iterator it = parameterMap.entrySet().iterator();
        while (it.hasNext()) {
            Map.Entry parmEntry = (Map.Entry) it.next();
            param.add(new BasicNameValuePair((String) parmEntry.getKey(),
                    (String) parmEntry.getValue()));
        }
        return param;
    }

    public static String printResponse(HttpResponse httpResponse)
            throws ParseException, IOException {
        // 获取响应消息实体
        HttpEntity entity = httpResponse.getEntity();
        // 响应状态
        log.debug("status:" + httpResponse.getStatusLine());
        log.debug("headers:");
        HeaderIterator iterator = httpResponse.headerIterator();
        while (iterator.hasNext()) {
            log.debug("\t" + iterator.next());
        }
        // 判断响应实体是否为空
        if (entity != null) {
            String responseString = EntityUtils.toString(entity);
            return responseString.replace("\r\n", "");
        }
        return "";
    }
}
